package com.dt.shirodemo.controller;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;


@Controller
public class UserController {

    @RequestMapping("/")
    public String index(){
        return "index";
    }

    @RequestMapping("/login")
    public String login(String username,String password, Model model){
        //创建一个Shiro 的 Subject 对象，lion给这个对象来完成用户的登录认证
        Subject subject = SecurityUtils.getSubject();

        //登出方法调用，用于清空登陆时的缓存信息，否则无法重复登陆
        subject.logout();

        //判断房钱用户是否已经认证过，如果已经认证过就不需要认证，否则进入if完成认证
        if (!subject.isAuthenticated()){
            //创建一个用户账号和密码的token对象，并设置用户输入的账号和密码
            //这个对象将在Shiro中被获取
            UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username, password);
            try{
                //例如账号不存在或密码错误等等，我们需要根据不同的异常类型来判断用户的登录状态并给与友好的信息展示
                subject.login(usernamePasswordToken);
            }catch (UnknownAccountException e){
                System.out.println("--------------------账号不存在");
                model.addAttribute("errorMessage","账号不存在");
                return "login";
            }catch(LockedAccountException e){
                //进入catch 表示用户的账号被锁定，这个异常是我们在后台抛出的
                System.out.println("====================账号被锁定");
                model.addAttribute("errorMessage","账号被锁定");
                return "login";
            }catch(IncorrectCredentialsException e){
                System.out.println("====================用户名密码不匹配");
                model.addAttribute("errorMessage","用户名密码不匹配");
                return "login";
            }
        }
        return "redirect:/success";
    }

    @RequestMapping("/success")
    public String success(){
        return "success";
    }

    @RequestMapping("/noPermission")
    public String noPermission(){
        return  "noPermission";
    }

    @RequiresRoles(value = {"user"})
    @RequestMapping("/user/test")
    public @ResponseBody String userTest(){
        // Subject subject= SecurityUtils.getSubject();
        // //验证当前用户是否拥有这个权限
        // subject.checkPermission("admin:add");
        // //验证当前用户是否拥有这个角色
        // subject.checkRole("admin");
        return "这是 userTest 请求";
    }

    @RequiresRoles(value = {"admin"})
    @RequestMapping("/admin/test")
    public @ResponseBody String adminTest(){

        return "这是 adminTest 请求";
    }

    @RequiresPermissions(value = {"admin:add"})
    @RequestMapping("/admin/add")
    public @ResponseBody String adminAdd(){

        return "这是 adminAdd 请求";
    }

    //配置一个 Spring 的异常监控，当工程抛出了 value 所指定的所以异常类型以后将直接进入到当前方法中
    @ExceptionHandler(value = {Exception.class})
    public String myError(Throwable throwable){
        //获取异常的类型，应该根据不同的异常类型进入到不通的页面显示不同提示信息
        System.out.println(throwable.getClass());
        System.out.println("---------------------------------");
        return "noPermission";
    }

//    注意：Shiro 验证失败以后会抛出异常，因此这时必须要配置一个 Spring 的异常监控方法myError 否则当前 Shiro 权限认证失败以后将无法转向到错误页面


}
